官方
http://research.microsoft.com/en-us/um/cambridge/groups/science/tools/d3/dynamicdatadisplay.htm
Tutorial
http://research.microsoft.com/en-us/um/cambridge/projects/ddd/d3isdk/
D3Overview 必读
http://research.microsoft.com/en-us/um/cambridge/groups/science/tools/d3/D3Overview.pdf
Sliverlight版本: DynamicDataDisplay.2.0.907
Dynamic Data Display 的Sliverlight版本和Wpf版本中的代码不一样.
Tutorial 3: Drawing dynamic heatmap
xaml1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<!-- Copyright © 2010-2011 Microsoft Corporation, All Rights Reserved.
-->
<UserControl x:Class="Tutorial3.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d3="clr-namespace:Microsoft.Research.DynamicDataDisplay;assembly=DynamicDataDisplay.Silverlight"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<d3:Chart>
<d3:Chart.Title>
<TextBlock HorizontalAlignment="Center" FontSize="14" Margin="0,5,0,5">Tutorial 3: Dynamic heatmap</TextBlock>
</d3:Chart.Title>
<d3:HeatmapGraph Name="heatmap" Palette="Blue,#00FF00,Red"/>
</d3:Chart>
</Grid>
</UserControl>
cs1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80// Copyright © 2010-2011 Microsoft Corporation, All Rights Reserved.
using System;
using System.Threading;
using System.Windows.Controls;
namespace Tutorial3
{
public partial class MainPage : UserControl
{
private volatile bool isUnloaded = false;
private Thread thread;
private double phase = 0;
public MainPage()
{
InitializeComponent();
// Start computation thread when page appears on the screen
Loaded += (s, e) =>
{
thread = new Thread(ModelRun);
isUnloaded = false;
thread.Start();
};
// Stop computation thread when page is removed from the screen
Unloaded += (s, e) =>
{
isUnloaded = true;
thread.Join();
};
}
/// <summary>Performs computations. Runs until isUnloaded became true.</summary>
private void ModelRun()
{
const int N = 1000;
const int M = 500;
// 1D arrays for grid
double[] x = new double[N + 1];
double[] y = new double[M + 1];
// Size of data array here is one less than size of the grid.
// HeatmapGraph will render in bitmap mode, when grid of size (N+1) x (M+1)
// defines N x M rectangular cells filled with solid color according to
// corresponding element of data array.
double[,] f = new double[N, M];
// Coordinate grid is constant and it is initialized once
for (int i = 0; i <= N; i++)
x[i] = -Math.PI + 2 * i * Math.PI / N;
for (int j = 0; j <= M; j++)
y[j] = -Math.PI / 2 + j * Math.PI / M;
while (!isUnloaded) // Run until page is on the screen
{
// Compute next iteration and store it in data array
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
f[i, j] = Math.Sqrt(x[i] * x[i] + y[j] * y[j])
* Math.Abs(Math.Cos(x[i] * x[i] + y[j] * y[j] + phase));
phase += 0.1;
// Uncomment next line to simulate delay in computations
// Thread.Sleep(1000);
// Plot the computed array.
//
// The Plot method must be called from the UI dispatcher thread.
// We pass a clone of the data array to the Plot method to prevent
// concurrent modification of the plotted data.
Dispatcher.BeginInvoke(
new Action<object>(data => heatmap.Plot((double[,])data, x, y)), f.Clone());
}
}
}
}
很常规的做法: 起一个线程用来做计算, 但Plot的调用必须在UI线程中, 因为heatmap是UI线程创建的; 注释已经写的比较明白了, 但在Discription中提到如下:
Please note that you need to use BeginInvoke to access UI elements from other threads and you need to clone all arrays that are changed in computation thread
here Plot method acts as asyncronous. It returns immediately and picture appears on the screen when it is completed. More complex approach when computation thread is waiting for each frame to be shown on the screen is present in code of tutorial
HeatmapGraph1
2
3
4
5
6
7
8
9System.Object
System.Windows.DependencyObject
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Panel
Microsoft.Research.DynamicDataDisplay.PlotBase
Microsoft.Research.DynamicDataDisplay.Plot
Microsoft.Research.DynamicDataDisplay.BackgroundBitmapRenderer
Microsoft.Research.DynamicDataDisplay.HeatmapGraph
Plot方法是异步的, 看看Plot1
2
3
4
5
6
7
8
9
10
11
12
13
14public long Plot(double[,] data, double[] x, double[] y, double missingValue)
{
HeatmapGraph.VerifyDimensions(data, x, y);
lock (this.locker)
{
this.xArr = x;
this.yArr = y;
this.data = data;
this.missingValue = missingValue;
this.dataVersion += 1L;
}
this.InvalidateBounds();
return base.QueueRenderTask();
}
base是指BackgroundBitmapRenderer1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/// <summary>
/// Base class for renderers, which can prepare its render results in a separate thread.
/// </summary>
public abstract class BackgroundBitmapRenderer : Plot
{
// Microsoft.Research.DynamicDataDisplay.BackgroundBitmapRenderer
/// <summary>Creates new render task and puts it to queue.</summary>
/// <returns>Async operation ID.</returns>
protected long QueueRenderTask()
{
long num;
this.nextID = (num = this.nextID) + 1L;
long num2 = num;
this.EnqueueTask(num2);
return num2;
}
}
关于BackgroundBitmapRenderer需要单独写一篇, 先暂且到这